package com.newcoin.xgb.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.newcoin.xgb.dto.QueryParameterDto;
import com.newcoin.xgb.dto.RechargeDto;
import com.newcoin.xgb.dto.WithdrawDto;
import com.newcoin.xgb.entity.*;
import com.newcoin.xgb.mapper.*;
import com.newcoin.xgb.po.*;
import com.newcoin.xgb.service.XgbAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class XgbAccountServiceImpl implements XgbAccountService {

    @Autowired
    private AccountMapper mapper;

    @Autowired
    private RechargeMapper rechargeMapper;

    @Autowired
    private WithdrawMapper withdrawMapper;

    @Autowired
    private BonusRecordMapper bonusRecordMapper;

    @Autowired
    private GrabOrdersRecordMapper grabOrdersRecordMapper;

    @Autowired
    private PayTheWayMapper payTheWayMapper;

    @Autowired
    private IncomeRecordMapper incomeRecordMapper;


    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private WithdrawConfigMapper withdrawConfigMapper;

    @Autowired
    private CommonMapper commonMapper;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private AssetRecordMapper assetRecordMapper;

    @Autowired
    private XgbUserBankMapper xgbUserBankMapper;


    @Value("${filePath}")
    private String filePath;


    @Override
    public Integer createAccount(Long userId) throws Exception {
        log.info("userId={}", userId);
        XgbAccount account = new XgbAccount();
        account.setUserId(userId);
        int row = mapper.insert(account);
        return row;
    }

    @Override
    public Result<XgbAccount> getAccount(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<XgbAccount> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        QueryWrapper<XgbAccount> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper.eq("user_id", queryParameterDto.getUserId());
        XgbAccount account = mapper.selectOne(accountQueryWrapper);
        account.setTodayTotalIncome(account.getFinancialTodayTotalIncome().add(account.getOrderGrabTodayTotalIncome()));
        account.setYesterdayTotalIncome(account.getFinancialYesterdayTotalIncome().add(account.getOrderGrabYesterdayTotalIncome()));
        account.setDynamicTotalIncome(account.getFinancialDynamicTotalIncome().add(account.getOrderGrabDynamicTotalIncome()));
        account.setTodayDynamicIncome(account.getFinancialTodayDynamicIncome().add(account.getOrderGrabTodayDynamicIncome()));
        result.setCode(200);
        result.setMessage("查询成功");
        result.setData(account);
        return result;
    }

    @Override
    public Result<RechargePo> getRecharge(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<RechargePo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbRecharge> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        QueryWrapper<XgbRecharge> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", queryParameterDto.getUserId())
                .orderByDesc("create_date");
        IPage<XgbRecharge> iPage = rechargeMapper.selectPage(page, queryWrapper);
        RechargePo rechargePo = new RechargePo();
        rechargePo.setCurrentPage(iPage.getCurrent());
        rechargePo.setTotalPages(iPage.getPages());
        rechargePo.setList(iPage.getRecords());
        result.setData(rechargePo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }

    @Override
    public Result<WithdrawPo> getWithdraw(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<WithdrawPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbWithdraw> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        QueryWrapper<XgbWithdraw> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", queryParameterDto.getUserId())
                .orderByDesc("create_date");
        if (queryParameterDto.getType() != 3) {
            queryWrapper.eq("state", queryParameterDto.getType());
        }
        IPage<XgbWithdraw> iPage = withdrawMapper.selectPage(page, queryWrapper);
        WithdrawPo withdrawPo = new WithdrawPo();
        withdrawPo.setCurrentPage(iPage.getCurrent());
        withdrawPo.setTotalPages(iPage.getPages());
        withdrawPo.setList(iPage.getRecords());
        result.setData(withdrawPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }

    @Override
    public Result<BonusRecordPo> getBonus(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<BonusRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbBonusRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        IPage<XgbBonusRecord> iPage = bonusRecordMapper.selectPage(page,
                new QueryWrapper<XgbBonusRecord>()
                        .eq("user_id", queryParameterDto.getUserId())
                        .eq("type", 1)
                        .orderByDesc("create_date"));
        BonusRecordPo bonusRecordPo = new BonusRecordPo();
        bonusRecordPo.setCurrentPage(iPage.getCurrent());
        bonusRecordPo.setTotalPages(iPage.getPages());
        bonusRecordPo.setList(iPage.getRecords());
        result.setData(bonusRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }


    @Override
    public Result<BonusRecordPo> getProxy(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<BonusRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbBonusRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        IPage<XgbBonusRecord> iPage = bonusRecordMapper.selectPage(page,
                new QueryWrapper<XgbBonusRecord>()
                        .eq("user_id", queryParameterDto.getUserId())
                        .eq("type", 4)
                        .orderByDesc("create_date"));
        BonusRecordPo bonusRecordPo = new BonusRecordPo();
        bonusRecordPo.setCurrentPage(iPage.getCurrent());
        bonusRecordPo.setTotalPages(iPage.getPages());
        bonusRecordPo.setList(iPage.getRecords());
        result.setData(bonusRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }

    @Override
    public Result<GrabOrdersRecordPo> getGrabOrdersRecord(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<GrabOrdersRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbGrabOrdersRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        QueryWrapper<XgbGrabOrdersRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", queryParameterDto.getUserId());
//        if (queryParameterDto.getType() != 2) {
//            queryWrapper.eq("state", queryParameterDto.getType());
//        }
        queryWrapper.orderByDesc("create_date");
        IPage<XgbGrabOrdersRecord> iPage = grabOrdersRecordMapper.selectPage(page, queryWrapper);
        GrabOrdersRecordPo grabOrdersRecordPo = new GrabOrdersRecordPo();
        grabOrdersRecordPo.setCurrentPage(iPage.getCurrent());
        grabOrdersRecordPo.setTotalPages(iPage.getPages());
        grabOrdersRecordPo.setList(iPage.getRecords());
        result.setData(grabOrdersRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }

    //获取已提交订单
    @Override
    public Result<GrabOrdersRecordPo> getCommittedOrders(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<GrabOrdersRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbGrabOrdersRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        QueryWrapper<XgbGrabOrdersRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", queryParameterDto.getUserId())
                .eq("state", 1)
                .orderByDesc("create_date");
        IPage<XgbGrabOrdersRecord> iPage = grabOrdersRecordMapper.selectPage(page, queryWrapper);
        GrabOrdersRecordPo grabOrdersRecordPo = new GrabOrdersRecordPo();
        grabOrdersRecordPo.setCurrentPage(iPage.getCurrent());
        grabOrdersRecordPo.setTotalPages(iPage.getPages());
        grabOrdersRecordPo.setList(iPage.getRecords());
        result.setData(grabOrdersRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }

    @Override
    public Result submitRecharge(RechargeDto rechargeDto) {
        log.info("RechargeDto={}", rechargeDto);
        Result<GrabOrdersRecordPo> result = new Result<>();
        if (loginVerification(rechargeDto.getUserId(), rechargeDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        if (rechargeDto.getAmount().compareTo(new BigDecimal("0")) < 0) {
            result.setCode(500);
            result.setMessage("请输入正确的充值金额");
            return result;
        }
        XgbRecharge xgbRecharge = new XgbRecharge();
        xgbRecharge.setUserId(rechargeDto.getUserId());
        xgbRecharge.setAmount(rechargeDto.getAmount());
        xgbRecharge.setVoucherAddress(rechargeDto.getUrl());

        int rows = rechargeMapper.insert(xgbRecharge);
        if (rows != 1) {
            result.setMessage("提交失败");
            result.setCode(500);
            return result;
        }
        result.setMessage("提交成功");
        result.setCode(200);
        return result;
    }

    //获取未提交订单
    @Override
    public Result<GrabOrdersRecordPo> getUncommittedOrders(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<GrabOrdersRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbGrabOrdersRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        QueryWrapper<XgbGrabOrdersRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", queryParameterDto.getUserId())
                .eq("state", 0)
                .orderByDesc("create_date");
        IPage<XgbGrabOrdersRecord> iPage = grabOrdersRecordMapper.selectPage(page, queryWrapper);
        GrabOrdersRecordPo grabOrdersRecordPo = new GrabOrdersRecordPo();
        grabOrdersRecordPo.setCurrentPage(iPage.getCurrent());
        grabOrdersRecordPo.setTotalPages(iPage.getPages());
        grabOrdersRecordPo.setList(iPage.getRecords());
        result.setData(grabOrdersRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }

    @Override
    public Result<Map<String, Object>> getRechargeAddress(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<Map<String, Object>> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Map<String, Object> map = new HashMap<>();
        XgbPayTheWay xgbPayTheWay = payTheWayMapper.selectById(1);
        map.put("bankAccount", xgbPayTheWay.getBankNum());
        map.put("bankInfo", xgbPayTheWay.getBankInfo());
        map.put("name", xgbPayTheWay.getName());
        result.setMessage("成功");
        result.setCode(200);
        result.setData(map);
        return result;
    }


    @Override
    public Result<BonusRecordPo> getIncomeRecord(QueryParameterDto queryParameterDto) throws Exception {
        Result<BonusRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbBonusRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        IPage<XgbBonusRecord> iPage = bonusRecordMapper.selectPage(page,
                new QueryWrapper<XgbBonusRecord>()
                        .eq("user_id", queryParameterDto.getUserId())
                        .eq("type", 5)
                        .orderByDesc("create_date"));
        BonusRecordPo bonusRecordPo = new BonusRecordPo();
        bonusRecordPo.setCurrentPage(iPage.getCurrent());
        bonusRecordPo.setTotalPages(iPage.getPages());
        bonusRecordPo.setList(iPage.getRecords());
        result.setData(bonusRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
        /*log.info("queryParameterDto={}", queryParameterDto);
        Result<IncomeRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbIncomeRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        IPage<XgbIncomeRecord> iPage = incomeRecordMapper.selectPage(page,
                new QueryWrapper<XgbIncomeRecord>()
                        .eq("user_id", queryParameterDto.getUserId())
                        .orderByDesc("create_date"));
        IncomeRecordPo incomeRecordPo = new IncomeRecordPo();
        incomeRecordPo.setCurrentPage(iPage.getCurrent());
        incomeRecordPo.setTotalPages(iPage.getPages());
        incomeRecordPo.setList(iPage.getRecords());
        result.setData(incomeRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;*/
    }


    @Override
    public Result<AssetRecordPo> getAssetRecord(QueryParameterDto queryParameterDto) {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<AssetRecordPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        Page<XgbAssetRecord> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        IPage<XgbAssetRecord> iPage = assetRecordMapper.selectPage(page,
                new QueryWrapper<XgbAssetRecord>()
                        .eq("user_id", queryParameterDto.getUserId())
                        .orderByDesc("create_date"));
        AssetRecordPo assetRecordPo = new AssetRecordPo();
        assetRecordPo.setCurrentPage(iPage.getCurrent());
        assetRecordPo.setTotalPages(iPage.getPages());
        assetRecordPo.setList(iPage.getRecords());
        result.setData(assetRecordPo);
        result.setCode(200);
        result.setMessage("成功");
        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result withdraw(WithdrawDto withdrawDto) throws Exception {
        log.info("withdrawDto={}", withdrawDto);
        Result<String> result = new Result<>();
        if (loginVerification(withdrawDto.getUserId(), withdrawDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbUsers users = usersMapper.selectOne(new QueryWrapper<XgbUsers>()
                .eq("id", withdrawDto.getUserId())
                .eq("pay_pwd", DigestUtils.md5DigestAsHex(withdrawDto.getPayPwd().getBytes())));
        if (users == null) {
            result.setCode(500);
            result.setMessage("交易密码错误");
            return result;
        }
        if (users.getIsWithdraw() == 0) {
            result.setCode(500);
            result.setMessage("您的账号暂时不能提现");
            return result;
        }
        if (users.getTodayOrderNum() < 60) {
            result.setCode(500);
            result.setMessage("今日抢单次数未达到60,不能提现");
            return result;
        }
        XgbWithdrawConfig withdrawConfig = withdrawConfigMapper.selectById(1);
        if (withdrawDto.getAmount().compareTo(withdrawConfig.getWithdrawFee()) <= 0) {
            result.setCode(500);
            result.setMessage("提现数量必须大于" + withdrawConfig.getWithdrawFee());
            return result;
        }
        XgbAccount account = mapper.selectOne(new QueryWrapper<XgbAccount>().eq("user_id", withdrawDto.getUserId()));
        if (account.getBalance().compareTo(withdrawDto.getAmount()) < 0) {
            result.setCode(500);
            result.setMessage("余额不足");
            return result;
        }

        UpdateWrapper<XgbAccount> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", withdrawDto.getUserId())
                .setSql("balance=balance-" + withdrawDto.getAmount());
        int row = mapper.update(null, updateWrapper);
        if (row != 1) {
            result.setCode(500);
            result.setMessage("提现失败");
            return result;
        }

        XgbUserBank xgbUserBank = xgbUserBankMapper.selectById(withdrawDto.getBankInfoId());

        XgbWithdraw xgbWithdraw = new XgbWithdraw();
        xgbWithdraw.setAmount(withdrawDto.getAmount().subtract(withdrawConfig.getWithdrawFee()));
        xgbWithdraw.setFee(withdrawConfig.getWithdrawFee());
        xgbWithdraw.setUserId(withdrawDto.getUserId());
        xgbWithdraw.setBankAccount(xgbUserBank.getCardNumber());
        xgbWithdraw.setBankName(xgbUserBank.getOpenBank()+xgbUserBank.getOpenBranchBank());
        xgbWithdraw.setName(xgbUserBank.getCardholder());
        row = row + withdrawMapper.insert(xgbWithdraw);
        if (row != 2) {
            throw new RuntimeException("提现失败");
        }

        result.setCode(200);
        result.setMessage("提现成功");
        return result;
    }

    @Override
    public Result<BigDecimal> getBalance(QueryParameterDto queryParameterDto) throws Exception {
        log.info("withdrawDto={}", queryParameterDto);
        Result<BigDecimal> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbAccount xgbAccount = mapper.selectOne(new QueryWrapper<XgbAccount>().eq("user_id", queryParameterDto.getUserId()));
        result.setCode(200);
        result.setMessage("成功");
        result.setData(xgbAccount.getBalance());
        return result;
    }


    private boolean loginVerification(Long userId, String token) {
        String redisToken = redisTemplate.opsForValue().get("token:" + userId);
        return (StringUtils.isEmpty(redisToken) || !redisToken.equalsIgnoreCase(token));
    }

    private static void generateQRCodeImage(String content, String name, int width, int height) {
        try {
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height);
//            Resource resource = new ClassPathResource("");
//            //resource.getFile().getAbsolutePath()+
//            Path path = FileSystems.getDefault().getPath("D:\\static\\address\\" + name + ".png");
            Path path = FileSystems.getDefault().getPath("/file/hqsr/address/" + name + ".png");
            MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
            log.info("保存完成");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
